<integersAsConcatOfVariableSizeDigits>

[START QUOTE FROM recursiveIntIterator.4.xml]
Try to define each transformation, starting from yi*(xs^ys)i, as a simple optimizable function.

How many inputs and outputs should each function have? 1 input and 1 output? 2 inputs and 1 output?

The goal is for the whole process to have 1 input (0 to yi*(xs^ys)i - 1) and 2 outputs (0 to xs^ys - 1, and 0 to xs*ys - 1).

It should later be optimized to this:
for(int yi=0; yi<ys; yi++){
	for(int xsPowerYsI=0; xsPowerYsI<xsPowerYsS; xsPowerYsI++){
		int xi = ...viewing xsPowerYsI as a base-xs number with ys quantity of digits, return digit number yi...;
		The 2 ints are xi and xsPowerYsI;
	}
}

Can I generalize * and ^ in the same way you can view an int as an int array size 32 containing 0 or 1 in each index?

xi*ys can be written as an int array size ys where each int is between 0 and xs-1.

xi*yi or (xs*ys)i can be written as an int array sie 2 with ranges 0 to xs-1, and 0 to ys-1.

A factorial function could be an int array where each index has a smaller range than the last, smaller by 1.


Is this type of variable-size digits useful for floating pointer numbers? Example: base-pi. Probably not.
But it could be useful for defining the floating point type as an int array size 64, or some smaller size using more bits of each int.


Should all ints be represented as the multiply of prime ints? Example: 100 is 2*2*5*5


Big integers could be represented as the multiply of prime ranges.
For example, 100^3 would be 12 ranges: 2*2*5*5*2*2*5*5*2*2*5*5


Does this optimization restrict sizes too much?: All ints must not have any prime as a factor more than once.
Examples: 1, 2, 3, 5, 2*3=6, 7, 2*5=10, 11, 13, 2*7=14, 3*5=15, 17, 19, 3*7=21, 2*11=22, 23, 2*13=26, 29, 2*3*5=30
The optimization is that small numbers can be written as 1 int where only the first 32 (or 31?) primes are available.
This prime optimization probably restricts things too much.


Trying again...
The goal is for the whole process to have 1 input (0 to yi*(xs^ys)i - 1) and 2 outputs (0 to xs^ys - 1, and 0 to xs*ys - 1).

If xs is 3 and ys is 5:

3^5 is 3*3*3*3*3
5*(3^5) is 5*3*3*3*3*3

Input 5*3*3*3*3*3, output 3*3*3*3*3 and 5*oneOfThe3s.

How would it know there are 5 3s if its all together like this 5*3*3*3*3*3?
[END QUOTE FROM recursiveIntIterator.4.xml]






Int array is the standard way to give a sequence of ints, but there are many other ways.
For example, a single int can be viewed as a 20 bit integer concat a 12 bit integer.
That uses all the bits and is aligned on bits, but it does not have to be.
For example, a number ranging 0 to 5-1 (alone is 3 bits), concat a number ranging 0 to 9-1 (alone is 4 bits),
can be stored as a number ranging 0 to 45-1 (alone is 6 bits, which is less than 3+4).
Not all of the 6 bits is used. It would have to range 0 to 64-1 for that. But its still smaller.

---Define a new type of number--- that is the concat of different size ranges.
For example, x is a concat of 3 ranges of size 10, 12, and 3. x ranges 0 to 360-1
and for each value of x, there are 3 values in those ranges.

This can represent the multiply * and power ^ functions.
x is the multiply of those 3 ranges.
If y is 3^5, then y is 3*3*3*3*3.

A normal Java int, if it does not become negative, ranges 0 to 2^31-1.
Maybe no single range should be allowed to exceed that, but combinations of ranges should.

The simplest of these new number types would be defined by an int array whose size is the number of ranges and whose content is the size of each range.
x = ranges 10, 12, and 3.
Definition of x = new int[]{10, 12, 3}.
If t is defined as {2, 5}, then could x be defined as {t, 12, 3}?

{{2,5}, 12, 3} can also be written as {2, 5, 12, 3}.
Can it be reordered and written as {5, 12, 2, 3}?

Power is more complex than multiply. Can things be combined similarly?
*(^(2 5) 12 3)
It can be expanded but its probably not useful: *(2 2 2 2 2 12 3)

Making them bigger and more similar may not be useful either:
*(^(2 5) ^(12 1) ^(3 1))
*( ^(2 5) *(^(12 1) ^(3 1)) )

Is (a^b)*(c^a) useful? I wrote about it somewhere else. It cant multiply 3*5.

Maybe a*(b^c) would be useful.
*(^(2 5) 12 3)
*^(
	*^(1 2 5)
	*^(
		*^(12 1 1)
		*^(3 1 1)
		1
	)
	1
)
*^( *^(12 3 1) 2 5 )
This *^ function probably is bad design. Use this instead: *(^(2 5) 12 3)

Does it simplify how variable quantity of concatted ranges are represented to use + and log (base 2)?
Quantity of bits of *(^(3 5) 12 7) is:
+(*(log(3) 5) log(12) log(7))
It is not simpler. It still has the same shape as *(^(3 5) 12 7) but with different functions.


Do not abbreviate by giving multiply more than 2 parameters. Write it this way:
*(^(3 5) *(12 7))




Maybe the functions that can be used to choose array size should have types and require their parameters be certain types.
An iteration has a root expression.
Each expression can give specific expressions (called childs) that can be derived from it in the context of iterating.
Some of these childs can be used for optimization, like [*(x y) --> *(y x) --> *(x y)] can be reduced to *(x y).
Sizes of all arrays is known at all times, so childs do not include that.

2 or any other positive integer.
No childs.
Iter: linear

range(x y) defines a range of integer sizes.
Child: x
Child y
Iter: linear

x or any other array that is not defined in terms of other arrays or integers.
No childs.
Iter: linear

^(x y) means [x power y], extends x.
No childs.
Iter: linear

*(x y) means [x multiply y], extends x.
Child: x
Child: y
Child: *(y x) //How to represent this in memory?
Iter: linear_x(linear_y): x, y.

*(^(x y) y) extends *(a b) //This is the most interesting of all combinations of * and ^.
Child: x
Iter: linear_xPowerY(linear_y): xPowerY, y, x.

*(*(x y) z) extends *(a b)
Child: *(x *(y z))
Iter: linear_x(linear_y(linear_z)): x, y, z.

^(^(x y) z) extends ^(a b)
Child: ^(x *(y z))

^(x *(y z)) extends ^(a b)
Child: ^(^(x y) z)

^(x 2) extends ^(a b)
Child: *(x x)

*(x x) extends *(a b)
Child: ^(x 2)



[QUOTE FROM ABOVE]
*(^(x y) y) extends *(a b) //This is the most interesting of all combinations of * and ^.
Child: x
Iter: linear_xPowerY(linear_y): xPowerY, y, x.
[END QUOTE FROM ABOVE]

Use *(^(x y) y) in a more complex expression, where x=*(f g) and y=*(f h):
*(^(*(f g) *(f h)) *(f h))
Child: *(f g) //x
Inherited child: ^(*(f g) *(f h)) //^(x y)
Inherited child: *(f h) //y
Iter: linear_[x]Power[Y](linear_[y]): [x]Power[Y], [y], [x].
Iter: linear_[*(f g)]Power[*(f h)]( linear_[*(f h)] ): [*(f g)]Power[*(f h)], [*(f h)], [*(f g)].
Recursively define an iterator in terms of f, g, and h.
Replace linear_[*(f h)] with linear_f(linear_h).
Iter: linear_[*(f g)]Power[*(f h)]( linear_f(linear_h) )
Replace 2 more multiplies.
Iter: linear_[linear_f(linear_g)]Power[linear_f(linear_h)]( linear_f(linear_h) )
That combination of linear loops is confusing.
Removing the word linear, it is written as: [f(g)]Power[f(h)]( f(h) )
Add the iteration vars that were removed above.
[f(g)]Power[f(h)]( f(h) ): [*(f g)]Power[*(f h)], [*(f h)], [*(f g)].
Writing it that way confuses array size with current iteration index.
Example: *(f h) means fIter*fSize + hIter.
Example: [f(g)]Power[f(h)] means (fSize*gSize)^(fSize*hSize).
Because ^(a b) has no childs, [f(g)]Power[f(h)] can only be iterated linearly, unless multiplied by f(h).
Maybe only the outputs of linear_[x]Power[Y](linear_[y]), which are [x]Power[Y], [y], and [x], should be divided more.
linear_[*(f g)]Power[*(f h)]( linear_[*(f h)] ): [*(f g)]Power[*(f h)], [*(f h)], [*(f g)].
Recurse on these outputs: [*(f g)]Power[*(f h)], [*(f h)], [*(f g)].
[*(f g)]Power[*(f h)], [f], [h], [f], [g].
Remove duplicate f.
All of these are linear iterations: [*(f g)]Power[*(f h)], [f], [h], [g].
Does it work on the original data?: *(^(*(f g) *(f h)) *(f h))
linear_f( linear_h( linear_g( linear_[*(f g)]Power[*(f h)] ) ) )
My intuition says the iteration size of *(^(*(f g) *(f h)) *(f h))...
...should be linear_f( linear_g( linear_[*(f g)]Power[*(f h)] ) ).
The [g] was not in my intuition predicted iteration size.
The [g] is redundant but maybe could be used if the expression included it somewhere else also.

Try this with an expression that can be reduced...
...to less iteration size than would be expected from the root nonrecursively:
Combine *(^(x y) *(g y)) with *(x y), where x=*(f g) and y=*(f h).
Combine *(^(*(f g) *(f h)) *(g *(f h))) with *(*(f g) *(f h)).
Rewrite *(^(*(f g) *(f h)) *(g *(f h))) as *(g *(^(*(f g) *(f h)) *(f h)))
Combine *(g *(^(*(f g) *(f h)) *(f h))) with *(*(f g) *(f h)).

*******************************************
Type of a node should be defined in an int array that is 3 times the size of the node as an Object array.
[indexInNode*3+0] = operator.
[indexInNode*3+1] = lvalue.
[indexInNode*3+2] = rvalue.

Operators include:
[0] = Define constant int. 1 parameter. Ignore second parameter.
[1] = Define duplicate size of something in this node. 1 parameter. Ignore second parameter. This is used to allow duplicate iterations, like x*x, which would have to be written as x*duplicate(x).
[2] = Define duplicate size of something in the static global Audivolv array. This is the only operator that can point outside the current node. Other operators in the node that need to do that must point at one of these instead. 1 parameter.
[3] = Define range. 2 parameters. Each
[5] = *. 2 parameters.
[6] = ^. 2 parameters.

Operator indexs will probably change, but must be constant for each run of Audivolv.

Type of each thing in a node (as an Object array) must also be specified. Maybe it should also be an int.
Should it be an index in the static global Audivolv array, and that location contains a representation of int[], double[], Object[], or some specific type of node (which is also Object[])?
[indexInNode*3+0] = type. //points at global array.
[indexInNode*3+1] = operator. //for calculating size.
[indexInNode*3+2] = lvalue. //for calculating size. Where this points depends on operator.
[indexInNode*3+3] = rvalue. //for calculating size. Where this points depends on operator.

Should lvalue and rvalue each have an int that tells where they point?
It could be global, thisNode, constantInt.
There would be less operators: duplicate, range, *, ^.
The duplicate operator could be removed.
[indexInNode*3+0] = type. //points at global array.
[indexInNode*3+1] = operator. //for calculating size. Possible values: range, *, ^.
[indexInNode*3+2] = lvaluePointsWhere. //for calculating size. Possible values: constantInt, global, specificTypeInGlobal (usually the type of this node).
[indexInNode*3+3] = lvalue. //for calculating size.
[indexInNode*3+4] = rvaluePointsWhere.
[indexInNode*3+5] = rvalue.

If lvaluePointsWhere or rvaluePointsWhere can point into the global array, then deleting and moving nodes from the global array becomes much more complex. Nodes dont have to be moved, but deleting them is necessary. To solve this, use the same solution used in the design of nodes, which is to use an Object array instead of int array.
value in Object[] = type. //points at global array.
value in int[]    = operator. //for calculating size. Possible values: range, *, ^. Reserve these indexs in global array to avoid confusion.
value in Object[] = lvaluePointsWhere. //for calculating size. Possible values: nodeThatMeansTypeOfConstantInt, nodeThatMeansGlobalArray, nodeThatIsASpecificType.
value in int[]    = lvalue. //for calculating size.
value in Object[] = rvaluePointsWhere.
value in int[]    = rvalue.

Change all int arrays except 1 to Object arrays. Represent int constants as 1 node each in the global array.
If type x has 5 arrays of type y and different sizes, and type y has 5 arrays of type z and different sizes, and type z has 5 arrays of type x and different sizes, what does it mean for one of those arrays in each x to be defined in terms of size of an array in type z in the context of y? If x also had some z arrays, it could also define arrays by the size of z in x.
Recursing only once, this is complex because x may have multiple array of y that each have z with different size arrays.
Should context be allowed to recurse farther?
It may complicate too much and be better to always refer to the current node or global array.

type = Object[]{
	int myUniqueInt[1]
	int intLiteralIsOnlyUsedIfThisTypeIsAnIntLiteral[1]
	Object typeAsNode[sizeOfInstanceNode]
	Object sizeAsNode[sizeOfInstanceNode]
}

If typeAsNode can be an operator [range, *, ^] or a type [bayesNode, neuralNode, or any type node],
then intLiteralIsOnlyUsedIfThisTypeIsAnIntLiteral is not needed.
If typeAsNode is one of the operators, then sizeAsNode must contain 2 type nodes whose sizes are lvalue and rvalue of that operator.

typeOrSizeExpression = Object[]{
	int myUniqueInt[1]
	Object typeOrOperatorAsNode[sizeOfInstanceNode]
	Object sizeExpression[sizeOfInstanceNode]
}

Example:
three = Object[]{
	int myUniqueInt[1]
	Object[]{ operatorMeansConstant }
	Object[]{ type3 }
}
type3 = Object[]{
	int myUniqueInt[1]
	Object any[3]
	Object any[3]
}
rangeThreeToFive = Object[]{
	int myUniqueInt[1]
	Object[]{ operatorMeansRange }???????
	Object[]{ type3, type5 }???????
}
someNodeType = Object[]{
	int myUniqueInt[1]
	Object types[]{ neuralNode, intArray, intArray, bayesianNode }
	Object sizes[]{ rangeThreeToFive, three, rangeThreeToFive, rangeThreeToFive }
}

Should the size types explicitly define possible iteration recursions? That would simplify things if the definition is not complex.
Example: (x^y)*y has 3 childs: (x^y), y, and x. But (x^y) has no childs.
Example: (x*y) has 2 childs: x and y.
There is no path from x^y to x*y, but there is a path from (x^y)*y to everywhere a path exists from x*y, therefore x^y and x*y can be used in the same iteration if iteration size includes (x^y)*y.

Should those childs be an extra Object array in each size type (but not the node type that uses the size type)?

Should only operator types should contain those childs? If specific size types contained them, the data may be redundant, but it has the advantage of not recalculating the recusion sizes, and the bigger advantage of choosing to exclude all recursion paths that are not used in the specific iteration.

rangeThreeToFive = Object[]{
	int myUniqueInt[1]
	Object sizeExpression[]{ operatorMeansRange, type3, type5 }
	int theIntConstant[0]
	Object iterRecurseChilds[0]
}
type3 = Object[]{
	int myUniqueInt[1]
	Object sizeExpression[]{ operatorMeansIntConstant }
	int theIntConstant[]{ 3 }
	Object iterRecurseChilds[0]
}

Should a size expression type be different than a node type?

rangeThreeToFive = Object[]{
	int myUniqueInt[1]
	int intSizeOperatorAndIntParams[]{ intOperatorMeansRange }
	Object sizeObjectParams[]{ type3, type5 }
	Object iterRecurseChilds[0]
}
type3 = Object[]{
	int myUniqueInt[1]
	int intSizeOperatorAndIntParams[]{ intOperatorMeansIntConstant, 3 }
	Object sizeObjectParams[0]
	Object iterRecurseChilds[0]
}

Make rangeThreeToFive with type3 be more similar:

rangeThreeToFive = Object[]{
	int myUniqueInt[1]
	int intOperatorThenParams[]{ intThatMeansRange, 3, 5 }
	Object objectOperatorThenParams[]{ notUsed1, notUsed2, notUsed3 }
	Object iterRecurseChilds[0]
}

rangeThreeToFiveTheLessEfficientWay = Object[]{
	int myUniqueInt[1]
	int intOperatorThenParams[]{ -1, -1, -1 }
	Object objectOperatorThenParams[]{ operatorMeansRange, type3, type5 }
	Object iterRecurseChilds[0]
}

rangeThreeToFiveBetweenThoseEfficiencies = Object[]{
	int myUniqueInt[1]
	int intOperatorThenParams[]{ intThatMeansRange, -1, 5 }
	Object objectOperatorThenParams[]{ notUsed1, type3, notUsed2 }
	Object iterRecurseChilds[0]
}

type3 = Object[]{
	int myUniqueInt[1]
	int intOperatorThenParams[]{ intThatMeansRange, 3, 3 }
	Object objectOperatorThenParams[]{ notUsed1, notUsed2, notUsed3 }
	Object iterRecurseChilds[0]
}

There is no path from x^y to x*y, but there is a path from (x^y)*y to everywhere a path exists from x*y, therefore x^y and x*y can be used in the same iteration if iteration size includes (x^y)*y.

x = rangeTwoToThree
y = rangeOneToTen

xPowerY = Object[]{
	int myUniqueInt[1]
	int intOperatorThenParams[]{ intThatMeansPower, -1, -1 }
	Object objectOperatorThenParams[]{ notUsed1, x, y }
	Object iterRecurseChilds[0]
}

xMultiplyY = Object[]{
	int myUniqueInt[1]
	int intOperatorThenParams[]{ intThatMeansMultiply, -1, -1 }
	Object objectOperatorThenParams[]{ notUsed1, x, y }
	Object iterRecurseChilds[]{ x y }
}

xPowerYThenMultiplyY = Object[]{
	int myUniqueInt[1]
	int intOperatorThenParams[]{ intThatMeansMultiply, -1, -1 }
	Object objectOperatorThenParams[]{ notUsed1, xPowerY, y }
	Object iterRecurseChilds[]{ xPowerY, x, y }
}


</integersAsConcatOfVariableSizeDigits>